Syntax20b.Scn.Fnt ParcElems Alloc Syntax24b.Scn.Fnt Syntax10.Scn.Fnt Syntax10b.Scn.Fnt Syntax10i.Scn.Fnt Syntax16.Scn.Fnt (* AMIGA *) MODULE Amiga; Data types, constants, variables, and procedures used to interface to the Amiga OS, and to link various high-level modules together. IMPORT SYSTEM, A:=AmigaAsl, D:=AmigaDos, E:=AmigaExec, G:=AmigaGraphics, I:=AmigaIntuition, U:=AmigaUtility, T:=AmigaTimer; CONST These default values are used, if no Oberon4Amiga environment variable was found. defaultHeight =800; defaultWidth = 1024; defaultDepth = 4; maxDepth = 8; The name of the environment variable used. envarcName is used for pre V39 AmigaOS, where the copy in the ENVARC: directory is not made automatically by SetEnv. envName = "Oberon4Amiga"; envarcName = "ENVARC:Oberon4Amiga"; The first value of the environment variable contains a version field. This is the current version. infoVersion = 6; pointerSize = 8; The title of the screen, and also the copyright notice appearing in the Log on system startup. screenTitle = "Oberon System V4 for Amiga V1.4"; TrapErr* = 0; ExceptionErr* = 1; SystemErr* = 2; (** values for ErrorFrame.type *) The sizes for the ChipMemPool PoolPuddleSize = 32768; PoolThreshSize = PoolPuddleSize DIV 2; Absolute=LONGINT; Module=LONGINT; NewProc*=PROCEDURE(tag:LONGINT):LONGINT; The content of the environment varibale. Currently it is stored binary, as is. All but the version field contain values needed for opening the initial screen. Info=RECORD version:LONGINT; displayID:LONGINT; height:INTEGER; width:INTEGER; depth:INTEGER; oscan:LONGINT; autoScroll:BOOLEAN; useWBWindow: BOOLEAN; modifyColors: BOOLEAN END; Real pointers declarations. The Amiga* modules only export these pointer types as LONGINT, to avoid problems with the garbage collection. ProcessPtr=POINTER TO D.Process; ScreenPtr=POINTER TO I.Screen; WindowPtr=POINTER TO I.Window; BitmapPtr=POINTER TO G.BitMap; RPPtr=POINTER TO G.RastPort; IOExtTimerPtr = POINTER TO T.TimeRequest; This is the Amiga specific way to store an Oberon pattern. PatternInfoPtr*= POINTER TO PatternInfo; PatternInfo*= RECORD modulo*: INTEGER; w*, h*: SHORTINT; data*: LONGINT; (* Pointer to individual pattern in chip mem. This pointer is used for patterns and Oberon fonts. *) offset*: INTEGER; (* Offset to individual pattern in chip mem. This offset is used for Amiga fonts. *) END; characters are patterns with additional informations needed by the Display.GetChar routine. They are not part of Patterns, because they are of now use as soon, as the character was "transformed" into a simple pattern by Display.GetChar. CharInfo*=RECORD (PatternInfo) (* Font related character info *) dx*, x*, y*: SHORTINT END; This is the Amiga specific representation of a font. Data and size point to a contiguos memory block which contains all character data (as they are build by the diskfont.library). Font*= POINTER TO FontInfo; FontInfo*= RECORD data*: LONGINT; (* Pointer to character data block in chip mem. *) size*: LONGINT; (* size of data block *) info*: ARRAY 256 OF CharInfo; amigaFont*: G.TextFontPtr; END; This contains the information needed as starting point to build a trap viewer. ErrorFrame*= RECORD PC-: LONGINT; (** PC value *) SP-: LONGINT; (** Stack Pointer *) FP-: LONGINT; (** Frame Pointer *) type-: LONGINT; (** type of error: TrapErr, ExceptionErr, SystemErr, 3 = Assertion, 4 = BreakPoint, 5 = Explicit *) val-: LONGINT (** type = TrapErr => trap number; type = ExceptionErr => exception mask (SET) *) END; Through this procedure variables, the routines from OLoad are called. For this to work, OLoad will patch in the address of a procedure into this variable. This can obviously work only, if the offset in memory of this variable is known. Therefore it is VERY IMPORTANT, that these variables remains the first declared variables in the module, and thus start at offset -4. The two guard variables are filled with some predefined values by OLoad so that on module initialisation it can be verifyed, if the variables have moved in respect to what OLoad expects . guard1:LONGINT; loaderCall:PROCEDURE(); guard2:LONGINT; These variables export the window and rast port which have to be used for the Oberon screen, as well as their dimensions. Depth-, OberonDepth-, ColorOffset-: INTEGER; Height-:INTEGER; Width-:INTEGER; window-: I.WindowPtr; WBWindow-: BOOLEAN; ModifyColors-: BOOLEAN; PensObtained: BOOLEAN; useLAltAsMouse enables the usage of the left alt key as a replacement for a middle mouse button, when only a two button mouse is available. This variable is initialised to TRUE. useLAltAsMouse*:BOOLEAN; This varible is initialised to the screen title. A read only variable is exported instead of the screenTitle constant, to avoid the generation of a new symbol file just because the string content has changed. version-:ARRAY 64 OF CHAR; idlePri*:SHORTINT; normalPri*:SHORTINT; thisTask- : E.TaskPtr; This is the stack pointer to which the trap handler has to return. It is remembered in Amiga.Loop and used in ???. stackPtr-: LONGINT; things for the Timer Device TicsToWait*: LONGINT; (*<=39 ChipMemPool-: E.MemPoolPtr; Flag for the Requester of System.Quit UseQuitRequester*: BOOLEAN; Arrays for Character Conversion Amiga <-> Oberon AtoO, OtoA: ARRAY 256 OF CHAR; Swaps the bits within a byte SwapBits- : ARRAY 256 OF SYSTEM.BYTE; misc Amiga gfx objects oldProcessWindow:I.WindowPtr; screen:I.ScreenPtr; pointerData: LONGINT; (*<=38 THEN GetDefaultMode(info,dummy); ChangeMode2(info); res:=0 ELSE res:=1 END ChangeMode; PROCEDURE DosCmd*(cmd, outName:ARRAY OF CHAR; VAR res:INTEGER); Run a program with STDIN set to NIL: and STDOUT set to output. in,out:D.FileHandlePtr; tags:ARRAY 4 OF U.TagItem; BEGIN in:=D.Open("NIL:",D.oldFile); ASSERT(in#0); out:=D.Open(outName,D.newFile); ASSERT(out#0); tags[0].tag:=D.sysInput; tags[0].data:=in; tags[1].tag:=D.sysOutput; tags[1].data:=out; tags[2].tag:=D.npCloseOutput; tags[2].data:=SYSTEM.VAL(LONGINT,FALSE); tags[3].tag:=U.done; res:=SHORT(D.System(cmd,tags)); IF D.Close(out) THEN END; IF D.Close(in) THEN END END DosCmd; PROCEDURE Loop*; This is the loop, which the loader calls instead of Oberon.Loop. It remembers the current stack pointer before calling Oberon.Loop, so the trap handler can return us into the loop, and we can restart Oberon.Loop after each trap. imported:ARRAY 32 OF CHAR; mod,modules:Module; oberonLoop:PROCEDURE; res:INTEGER; BEGIN ThisMod("Oberon",mod,res,modules,imported); Assert(res=0,"Amiga.Loop: Oberon not found"); ThisCommand(mod,"Loop",SYSTEM.VAL(Absolute,oberonLoop),res); Assert(res=0,"Amiga.Loop: Oberon.Loop not found"); LOOP SaveRegs; SYSTEM.GETREG(15,stackPtr); DEC(stackPtr,4); (* stack pointer value after call of oberonLoop. *) oberonLoop; LoadRegs END Loop; PROCEDURE InitSwapBits; Init swaps array to swap the bits within a byte [76543210] -> [01234567] VAR i,j, in,res:INTEGER; BEGIN FOR j:=0 TO 255 DO res:=0; in:=j; FOR i:=0 TO 7 DO res:=res*2+in MOD 2; in:=in DIV 2 END; SwapBits[j] := CHR(res); END; END InitSwapBits; PROCEDURE Init; Get the screen infos and initialize the Oberon screen and window. Install a blank sprite as pointer. Install the termination procedure for all this. Initialise the gloabl variables for character conversion and middle mouse button replacement. fromEnv:BOOLEAN; info:Info; proc:ProcessPtr; scr:ScreenPtr; scrrp:RPPtr; tags:ARRAY 13 OF U.TagItem; win:WindowPtr; bm: BitmapPtr; i: INTEGER; PROCEDURE OpenScreen(); BEGIN Depth:=info.depth; OberonDepth:=Depth; Height:=info.height; Width:=(info.width DIV 8)*8; tags[0].tag:=I.saDepth; tags[0].data:=info.depth; tags[1].tag:=I.saHeight; tags[1].data:=Height; tags[2].tag:=I.saWidth; tags[2].data:=Width; tags[3].tag:=I.saDisplayID; tags[3].data:=info.displayID; tags[4].tag:=I.saQuiet; tags[4].data:=-1; tags[5].tag:=I.saAutoScroll; tags[5].data:=-1; tags[6].tag:=I.saOverscan; tags[6].data:=info.oscan; tags[7].tag:=I.saBehind; tags[7].data:=-1; tags[8].tag:=I.saDetailPen; tags[8].data:=0; tags[9].tag:=I.saBlockPen; tags[9].data:=SYSTEM.LSH(1,Depth)-1; tags[10].tag:=I.saTitle; tags[10].data:=SYSTEM.ADR(screenTitle); tags[11].tag:=I.saInterleaved; tags[11].data:=-1; tags[11].tag:=U.done; screen:=I.OpenScreenTags(0(*NIL*),tags); scr := SYSTEM.VAL(ScreenPtr, screen); Assert(scr#NIL,"No screen"); tags[0].tag:=I.waCustomScreen; tags[0].data:= screen; tags[1].tag:=I.waIDCMP; tags[1].data:=SYSTEM.VAL(LONGINT, {I.rawKey,I.mouseButtons(*,I.mouseMove*)}); tags[1].data:=SYSTEM.VAL(LONGINT, {}); (* For new Input *) (*<=39 THEN ChipMemPool:=E.CreatePool({E.memChip}, PoolPuddleSize, PoolThreshSize); Assert(ChipMemPool#0, "Can not create memory pool for fonts") ELSE ChipMemPool:=0 END; IF ChipMemPool#0 THEN pointerData:=E.AllocPooled(ChipMemPool, pointerSize); ELSE pointerData:=E.AllocMem(pointerSize,{E.memChip,E.memClear}) END; InitSwapBits; version:=screenTitle; IF A.aslVersion>=38 THEN GetDefaultMode(info,fromEnv); IF ~fromEnv THEN ChangeMode2(info); GetDefaultMode(info,fromEnv) END ELSE GetDefaultMode(info,fromEnv) END; WBWindow:=info.useWBWindow; ModifyColors:=info.modifyColors; IF WBWindow THEN OpenWBWindow() ELSE OpenScreen() END; thisTask:=E.FindTask(0); proc:=SYSTEM.VAL(ProcessPtr,thisTask); oldProcessWindow:=proc.windowPtr; proc.windowPtr:=window; I.SetPointer(window,pointerData,0,0,0,0); I.ActivateWindow(window); scrrp:=SYSTEM.VAL(RPPtr, SYSTEM.ADR(scr.rastPort)); bm:=SYSTEM.VAL(BitmapPtr, scrrp.bitMap); Depth:=bm.depth; IF info.depth<=Depth THEN OberonDepth:=info.depth ELSE OberonDepth:=Depth END; TermProcedure(Close); useLAltAsMouse:=TRUE; idlePri:=-128; normalPri:=0; TicsToWait:=20000; PrinterName:="PrinterOut.ps"; PictPrintThresh:=128; UseQuitRequester:=FALSE; END Init; BEGIN stackPtr:=0; Ensure, that OLoad probably guessed right, when patching in loaderCall. Assert((guard1=002468ACEH) & (guard2=013579BDFH),"Amiga: wrong loader call guards."); Init END Amiga.